YY的GCD
Time Limit: 10 Sec Memory Limit: 512 MB
Description
求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对k。
第一行一个整数T 表述数据组数接下来T行,每行两个正整数,表示N, M。
Output
T行,每行一个整数表示第 i 组数据的结果
2
10 10
100 100
Sample Output
30
2791
HINT
T = 10000
N, M <= 10000000
Solution
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| #include<bits/stdc++.h> using namespace std; typedef long long s64;
const int ONE = 10000005;
int T; int n,m; bool isp[ONE]; int prime[700005],p_num; int miu[ONE],sum[ONE]; s64 Ans;
int get() { int res=1,Q=1; char c; while( (c=getchar())<48 || c>57) if(c=='-')Q=-1; if(Q) res=c-48; while((c=getchar())>=48 && c<=57) res=res*10+c-48; return res*Q; }
void Getmiu(int MaxN) { miu[1] = 1; for(int i=2; i<=MaxN; i++) { if(!isp[i]) prime[++p_num] = i, miu[i] = -1; for(int j=1; j<=p_num, i*prime[j]<=MaxN; j++) { isp[i * prime[j]] = 1; if(i % prime[j] == 0) { miu[i * prime[j]] = 0; break; } miu[i * prime[j]] = -miu[i]; } } for(int j=1; j<=p_num; j++) for(int i=1; i*prime[j]<=MaxN; i++) sum[i * prime[j]] += miu[i]; for(int i=1; i<=MaxN;i++) sum[i] += sum[i-1]; }
void Solve() { n=get(); m=get(); if(n > m) swap(n,m); Ans = 0; for(int i=1, j=0; i<=n; i=j+1) { j = min(n/(n/i), m/(m/i)); Ans += (s64) (n/i) * (m/i) * (sum[j] - sum[i-1]); } printf("%lld\n",Ans); }
int main() { Getmiu(ONE-1); T=get(); while(T--) Solve(); }
|